from activation_functions.sigmoid import ActivationSigmoid
from util.matrix import Matrix

__author__ = 'Douglas'


class FeedforwardLayer:
    def __init__(self, neuron_count, activation_function=ActivationSigmoid()):
        self.fire = [0.0] * neuron_count
        self.matrix = None
        self.__next = None
        self.previous = None
        self.activation_function = activation_function

    def compute_outputs(self, pattern=None):
        if pattern is not None:
            self.fire = [i for i in pattern]

        input_matrix = Matrix([[i for i in self.fire] + [1]])
        # add a "fake" first column to the input so that the threshold is
        # always multiplied by one, resulting in it just being added.

        for i in range(self.next.neuron_count):
            col = self.matrix.get_column(i)
            s = (input_matrix * col)[0][0]
            self.next.fire[i] = self.activation_function.activation_function(s)

        return self.fire

    @property
    def neuron_count(self):
        return len(self.fire)

    @property
    def is_hidden(self):
        return False if self.is_input or self.is_output else True

    @property
    def is_input(self):
        return True if self.previous is None else False

    @property
    def is_output(self):
        return True if self.next is None else False

    def reset(self):
        if self.matrix is not None:
            self.matrix = self.matrix.ramdomize(-1, 1)

    @property
    def next(self):
        return self.__next

    @next.setter
    def next(self, next_layer):
        self.__next = next_layer
        self.__next.previous = self
        self.matrix = Matrix(self.neuron_count + 1, next_layer.neuron_count)